In this tutorial, we will synthesize a sine tone from an array of values and plot it. We'll listen to the signal in the notebook and also export it as a WAV file. Finally, we'll import a WAV file and crop it.
First, we need to import NumPy, a python package for scientific computing.
import numpy as np
Next, we'll create variables to hold the frequency, duration, and sampling rate of our sine tone. Let's generate a tone at 440 Hz that lasts 3 seconds long with a sampling rate of 22050 Hz.
freq = 440
dur = 3.0
fsamp = 22050
%whos
We can make an array of time values, t, which contains each point in time that we want a sample. The np.linspace function below creates an array of 66,150 evenly spaced numbers ranging from 0 to 3.
t = np.linspace(0, dur, int(dur * fsamp), endpoint=False)
Since the t array is very long, only the first few and last few values are displayed below.
t
To generate a sine tone, at each point in time, we want to plug our current t value into a sine function.
$$x = \sin( 2 \pi f t)$$NumPy's np.sin function lets us plug an array of time values in and get an array of output values. We'll store the output in a variable called x.
x = np.sin(2 * np.pi * freq * t)
x
Looking at just these few values, it's hard to tell we made a sine wave. Let's visualize it.
First we need to import matplotlib.pyplot for creating plots.
import matplotlib.pyplot as plt
The following line allows plots to be visible within the notebook.
%matplotlib inline
First, the plt.figure line below allows us to adjust the size of the figure. Then, we simply call plt.plot to plot the signal. The semi colon suppresses output from python.
plt.figure(figsize=(16,3))
plt.plot(t, x);
This just looks like a blue rectangle since the sine wave oscillates quickly in a short space. To see the sine wave, we'll use plt.xlim to crop the plot's range along the x axis. Let's look at just the first 5 milliseconds. Also we'll label the seconds along the x axis.
plt.figure(figsize=(16,3))
plt.xlim(0,0.005)
plt.xlabel("time (sec)");
plt.plot(t, x);
Now that we've visualized our signal, let'ls listen to it.
Using IPython.display.Audio, we can listen to an audio signal from a NumPy array. Let's import IPython display.
import IPython.display as ipd
Now we just need to give the ipd.Audio function our signal x and its sampling rate fsamp, and we can play the sound right in the notebook.
ipd.Audio(x, rate=fsamp)
In addition to listening to a signal in the notebook, we can export it as a WAV file using the Librosa audio signal processing library. Let's import it.
import librosa
To export an array as a sound file we can use the librosa.output.write_wav function. Simply pass it the signal, its sampling rate, and the desired filename.
librosa.output.write_wav("sine_440_3s.wav", x, fsamp)
Now, there should be an audio file called 'sine_440_3s.wav' saved in the same directory as this notebook.
We can also import audio from a WAV file into a numpy array using Librosa. Let's import the audio file taxman.wav, which should be saved in the same directory as this notebook. The librosa.load function will return the audio signal as an array, y, as well as its sampling rate.
y, fsamp_y = librosa.load("taxman.wav")
Let's visualize the signal y and listen to it. This time we'll plot with librosa.display.waveplot, which is useful for cleanly displaying the amplitude envelope of time domain audio signals.
import librosa.display
plt.figure(figsize=(16,3))
librosa.display.waveplot(y, fsamp_y)
ipd.Audio(y, rate=fsamp_y)
fsamp_y
Finally, let's edit this audio signal by cropping a 5 second clip of the beginning. We'll compute the clip length in samples using the sampling rate.
clip_length = fsamp_y * 5
clip_length
We can use simple array slicing to do the cropping.
clip_y = y[:clip_length]
len(clip_y)
Let's plot, listen to, and export our clip.
#plot
plt.figure(figsize=(16,3))
librosa.display.waveplot(clip_y, fsamp_y);
#listen
ipd.Audio(clip_y,rate=fsamp_y)
#export
librosa.output.write_wav("taxman_5s.wav", clip_y, fsamp_y)